package common.interfaces;

import java.io.File;
import java.sql.SQLException;
import java.util.List;
import java.util.SortedSet;

import common.enums.AnswerEnum;
import common.types.FictionalCharacter;
import common.types.Pair;
import common.types.StatisticsEntry;

public interface DBInterface {
	
	/**
	 * This method query characters from DB by <code>name</code>. </br>It will query characters that have
	 * <code>name</code> as part of there name. </br>For example: for name "spider" will query characters
	 * having the name "The amazing spiderman", "spiderman" and so on...
	 * 
	 * @param name
	 * @param limit - Limit for the length of the results list.
	 * @return A pair holding a List of the found characters and the amount of results that were actually found.
	 * @throws Exception
	 */
	public Pair<List<FictionalCharacter>,Integer> queryCharacter(String name, int limit) throws Exception;
	
	/**
	 * This method removes the character having the key <code>CID</code>.
	 * 
	 * @param CID - The character key.
	 * @return True if success and False if CID wasn't found.
	 * @throws Exception
	 */
	public boolean removeCharacter(int CID) throws Exception;
	
	/**
	 * This method updates the character information in DB.
	 * 
	 * @param character - The update.
	 * @return True if success and False if CID wasn't found.
	 * @throws Exception
	 */
	public boolean updateCharacter(FictionalCharacter character) throws Exception;
	
	/**
	 * This method creates a new character in DB.
	 * 
	 * @param character - The new character.
	 * @return True if success and False if already exist.
	 * @throws Exception
	 */
	public boolean createCharacter(FictionalCharacter character) throws Exception;
	
	/**
	 * 
	 * @return A major session id. differs from a session ID by the fact that only one is 
	 * recieved when the gui starts (not on every new game). Used to query if importing/editing is allowed
	 * returns -1 if someone else is currently in edit mode (import). (or if some error occured)
	 * @throws SQLException
	 */
	public int getNewGUISessionID() throws Exception;
	
	/**
	 * @return A new unique session ID.
	 * @throws Exception
	 */
	public int getNewGameSessionID() throws SQLException;
	
	/**
	 * This method runs and analysis that calculates the best cutting attributes and values.
	 * 
	 * @param SID - Session ID.
	 * @throws Exception
	 */
	public void runAnalysis(int SID) throws Exception;
	
	/**
	 * This method gets the best cutting value and its related attribute PID.
	 * 
	 * @param SID - Session ID.
	 * @param index - The index of the best attribute and value.
	 * @return A pair holding the name of the value and its related attribute PID.
	 * @throws Exception
	 */
	public Pair<String,Integer> getBestCut(int SID, int index) throws Exception;
	
	/**
	 * @param PID
	 * @return The question template of the given PID.
	 * @throws Exception
	 */
	public String getQuestionTemplate(int PID) throws Exception;
	
	/**
	 * This method cuts the possible guesses for the given session by the answer of the PID question.
	 * 
	 * @param SID - Session ID
	 * @param PID
	 * @param answer - The answer to cut with. 
	 * @throws Exception
	 */
	public void makeCut(int SID, int PID, AnswerEnum answer) throws Exception;
	
	/**
	 * @param SID - Session ID
	 * @return True if only one possible guess is left for the given SID.
	 * @throws Exception
	 */
	public boolean isGuessReady(int SID) throws Exception;
	
	/**
	 * @param SID - Session ID
	 * @return The best guess for the given SID. (Pair<Character ID, Character Name>)
	 * @throws Exception
	 */
	public Pair<Integer, String> getBestGuess(int SID) throws Exception;
	
	/**
	 * This method submits the user's actual guess.
	 * 
	 * @param CID - Guessed character ID.
	 * @param isCorrect - True if guess was correct.
	 * @param actual - Actual character chosen by user.
	 * @throws Exception
	 */
	public void submitActual(int CID, boolean isCorrect, String actual) throws Exception;	
	
    /**
     * This method cleans the DB from the information related to the major SID.
     * 
     * @param majorSID - Major session ID
     * @throws Exception
     */	
	public void cleanGUISession(int majorSID) throws Exception;
	
	/**
	 * Tries setting the edit mode bit in MajorSession table
	 * @param majorSID
	 * @return true if succeed, false otherwise (becuase there are other readers or one writer)
	 */
	public boolean requestEditMode(int majorSID) throws Exception;

	 /**
     * Unset the edit mode bit in MajorSession table
     * @param majorSID
     * @return true if succeed, false otherwise (becuase there are other readers or one writer)
     */
	public void endEditMode(int majorSID) throws Exception;
	
	/**
	 * This method cleans the DB from the information related to the SID.
	 * 
	 * @param SID - Session ID
	 * @throws Exception
	 */
	public void cleanGameSession(int SID) throws Exception;
	
	/**
	 * @return False if there are old session ID's in the working tables.
	 * @throws Exception
	 */
	public boolean isCleanDB() throws Exception;
	
	/**
	 * This methods cleans all the old session ID's from the working tables.
	 * 
	 * @throws Exception
	 */
	public void garbageCollection() throws Exception;
	
	/**
	 * @return A pair holding the statistics history and the total correct guesses.
	 * @throws Exception
	 */
	public Pair<SortedSet<StatisticsEntry>,Integer> queryStatisticsHistory() throws Exception;
	
	/**
	 * @param freeBaseRoot a file reference to the root of the fictional_universe untarred file
	 * @return ture on success, false otherwise
	 * @throws Exception
	 */
	public boolean importToDB(File freeBaseRoot) throws Exception;
	
	
	/**
	 * Releases all database resources
	 */
	public void close() throws Exception;
	
	/**
	 * Removes all guiSessions if guiSessionID == -1, and all but guiSessionID otherwise
	 * @throws Exception
	 */
    void forceGuiSessionCleanup(int guiSessionID) throws Exception;
}
